import re
import os
import requests
import time
from fastapi import HTTPException
from settings import BILIBILI_HEADERS
from components.dbOperations import (
    get_course_series, create_course_series,
    get_part_by_series_and_page, create_course_parts_batch
)

def extract_bv_and_p_from_url(url):
    """从B站URL中提取BV号和分P号"""
    bv_match = re.search(r'BV\w{10}', url)
    if not bv_match:
        raise ValueError("无法从URL中提取BV号")
    
    bv_number = bv_match.group()
    p_match = re.search(r'[?&]p=(\d+)', url)
    p_number = int(p_match.group(1)) if p_match else 1
    return bv_number, p_number

def get_video_info(bv_number, max_retries=3):
    """从B站API获取视频的元数据信息"""
    for attempt in range(max_retries):
        try:
            view_url = f"https://api.bilibili.com/x/web-interface/view?bvid={bv_number}"
            response = requests.get(view_url, headers=BILIBILI_HEADERS, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data['code'] != 0:
                raise Exception(f"获取视频信息失败: {data['message']}")
                
            return data['data']
            
        except requests.exceptions.RequestException as e:
            if attempt == max_retries - 1:
                raise Exception(f"网络请求失败: {str(e)}")
            print(f"第{attempt + 1}次请求失败，正在重试...")
            time.sleep(1)
        except Exception as e:
            raise Exception(f"获取视频信息时发生错误: {str(e)}")

def get_video_cid_aid(meta_data, p_number):
    """从元数据中获取指定分P的cid和aid"""
    pages = meta_data.get("pages", [])
    if not pages:
        return meta_data["cid"], meta_data["aid"]
    if p_number > len(pages):
        raise ValueError(f"错误：视频只有{len(pages)}个分P，无法下载第{p_number}P")
    page = pages[p_number - 1]
    return page["cid"], meta_data["aid"]

async def ensure_bilibili_video_exists(bv_number: str, meta_data: dict) -> str:
    """确保课程系列和分P信息存在于数据库中"""
    try:
        series = get_course_series(unique_id=bv_number)
        if not series:
            # 创建系列
            series = create_course_series(
                unique_id=bv_number,
                title=meta_data['title'],
                description=meta_data['desc'],
                pic=meta_data['pic'],
                owner=meta_data['owner']['name'],
                face=meta_data['owner']['face'],
                source='bilibili'
            )
            series_id = series['series_id']
            
            # 准备批量插入的数据
            parts_data = [
                {
                    'series_id': series_id,
                    'title': page['part'],
                    'page': page['page'],
                    'status': 0,
                    'duration': int(page.get('duration', 0))
                }
                for page in meta_data['pages']
            ]
            await create_course_parts_batch(parts_data)
        else:
            series_id = series[0]['series_id']
        return series_id
    except Exception as e:
        print(f"创建视频记录失败: {str(e)}")
        raise

async def get_video_base_info(url: str) -> tuple:
    """获取视频基础信息和数据库记录"""
    vid, page = extract_bv_and_p_from_url(url)
    series = get_course_series(unique_id=vid)
    
    if not series:
        meta_data = get_video_info(vid)
        series_id = await ensure_bilibili_video_exists(vid, meta_data)
        series = get_course_series(series_id=series_id)

    part_info = get_part_by_series_and_page(series[0]['series_id'], page)
    if not part_info:
        raise HTTPException(status_code=404, detail="未找到对应的分P信息")
    return vid, page, series[0], part_info

